package com.zenchn.controller;

import com.zenchn.annotation.OperLog;
import com.zenchn.entity.HttpDataResult;
import com.zenchn.entity.TSysDictVO;
import com.zenchn.enums.OperLogActionEnum;
import com.zenchn.exception.CheckException;
import com.zenchn.model.TSysDict;
import com.zenchn.model.TSysDictExample;
import com.zenchn.model.TSysDictType;
import com.zenchn.service.DictService;
import com.zenchn.service.DictTypeService;
import com.zenchn.utils.CommonUtils;
import io.swagger.annotations.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 数据字典信息模块控制器
 *
 * @author dingxinfa
 * @date 2020-04-20
 **/

@RestController
@RequestMapping(value = "dictInfo")
@Api(value = "数据字典信息模块相关接口",tags="系统管理-数据字典")
@RequiresPermissions("data:dict")
public class DictInfoController {
    private final String MODULE="系统管理>数据字典";

    @Resource
    private DictService dictService;

    @Resource
    private DictTypeService dictTypeService;
    /**
     * 获取数据字典列表
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module=MODULE,action= OperLogActionEnum.QUERY,detail="获取数据字典列表")
    @ApiOperation(value = "获取数据字典列表", notes = "获取数据字典列表")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "keyword", value = "字典名称，字典编码，字典值"),
            @ApiImplicitParam(dataType = "String", name = "dictTypeId", value = "字典类型ID"),
            @ApiImplicitParam(dataType = "Boolean", name = "isEnable", value = "是否启用")
    })
    @GetMapping(value = "/list")
    @RequiresPermissions("data:dict")
    public ResponseEntity<HttpDataResult<List<TSysDictVO>>> list(
            @RequestParam(required = false, value = "dictTypeId") String dictTypeId,
            @RequestParam(required = false, value = "keyword") String keyword,
            @RequestParam(required = false, value = "isEnable") Boolean isEnable,
            HttpServletRequest request, HttpServletResponse response) throws Exception{
        HttpDataResult<List<TSysDictVO>> result = new HttpDataResult<>(request.getRequestURI());

        List<TSysDictVO> dictVOList=dictService.selectCascadeDictList(dictTypeId,keyword,isEnable);

        result.setData(dictVOList);

        result.setMessage("OK");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

    /**
     * 新增数据字典保存提交
     * @param dict
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module=MODULE,action= OperLogActionEnum.INSERT,detail="新增数据字典保存提交")
    @ApiOperation(value = "新增数据字典保存提交", notes = "新增数据字典保存提交")
    @ApiParam(type = "TSysDict", name = "dict", value = "数据字典对象", required = true)
    @PostMapping(value = "/addSubmit")
    @RequiresPermissions("data:dict:add")
    public ResponseEntity<HttpDataResult<String>> addSubmit(
            @RequestBody @Valid TSysDict dict, BindingResult results,
            HttpServletRequest request, HttpServletResponse response) throws Exception{
        HttpDataResult<String> result = new HttpDataResult<>(request.getRequestURI());

        if (results.hasErrors()){
            throw new CheckException(Objects.requireNonNull(results.getFieldError()).getDefaultMessage());
        }

        //初始化数据字典层级信息
        initDictLevel(dict);

        dict.setCreateTime(LocalDateTime.now());
        dict.setDictId(CommonUtils.randomUUID());
        dictService.insert(dict);

        result.setData(dict.getDictId());

        result.setMessage("新增数据字典成功。");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);

    }

    /**
     * 初始化数据字典层级信息
     * @param dict
     */
    private void initDictLevel(TSysDict dict){
        TSysDictType dictType=dictTypeService.selectByPrimaryKey(dict.getDictTypeId());
        if (dictType.getIsCascade()){
            if(null!=dict.getParentId() && !"".equals(dict.getParentId().trim())){
                TSysDict pDict=dictService.selectByPrimaryKey(dict.getParentId());
                dict.setDataLevel(pDict.getDataLevel()+1);
            }else{
                dict.setDataLevel(1);
                dict.setParentId(null);
            }
        }else{
            dict.setDataLevel(1);
            dict.setParentId(null);
        }
    }

    /***
     * 修改数据字典
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module=MODULE,action= OperLogActionEnum.QUERY,detail="修改数据字典UI数据接口")
    @ApiOperation(value = "修改数据字典UI数据接口", notes = "修改数据字典UI数据接口")
    @ApiImplicitParam(dataType = "String", name = "dictId", value = "数据字典ID", required = true)
    @GetMapping(value = "/modify")
    public ResponseEntity<HttpDataResult<Map<String,Object>>> modify(
            @RequestParam(value = "dictId") String dictId,
            HttpServletRequest request, HttpServletResponse response) throws Exception{
        HttpDataResult<Map<String,Object>> result = new HttpDataResult<>(request.getRequestURI());
        Map<String,Object> resultData=new HashMap<>(16);

        TSysDict dict=dictService.selectByPrimaryKey(dictId);
        resultData.put("dict", dict);
        TSysDictType dictType=dictTypeService.selectByPrimaryKey(dict.getDictTypeId());
        resultData.put("isCascade", dictType.getIsCascade());
        if (dictType.getIsCascade()) {
            //获取父级路径
            if (null != dict.getParentId() && !"".equals(dict.getParentId().trim())) {
                List<TSysDict> fullCascadeList = dictService.findFullCascadeParent(dict.getParentId());
                resultData.put("parentList", assembleSysDictVO(new LinkedList(fullCascadeList)));
            }
        }

        result.setData(resultData);
        result.setMessage("OK");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

    /***
     * 组装整合已选择级联数据字典数据
     * @param dictList
     * @return
     */
    private List<TSysDictVO> assembleSysDictVO(LinkedList<TSysDict> dictList){
        List<TSysDictVO> dictVOList=new ArrayList<>();

        TSysDict dict=dictList.pollFirst();
        if (null!=dict) {
            TSysDictVO dictVO=new TSysDictVO();
            BeanUtils.copyProperties(dict,dictVO);
            if (!dictList.isEmpty()) {
                dictVO.setChildren(assembleSysDictVO(dictList));
            }
            dictVOList.add(dictVO);
        }
        return dictVOList;
    }

    /**
     * 修改数据字典保存提交
     * @param dict
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module=MODULE,action= OperLogActionEnum.UPDATE,detail="修改数据字典保存提交")
    @ApiOperation(value = "修改数据字典保存提交", notes = "修改数据字典保存提交")
    @ApiParam(type = "TSysDict", name = "dict", value = "数据字典对象", required = true)
    @PutMapping(value = "/modifySubmit")
    @RequiresPermissions("data:dict:modify")
    public ResponseEntity<HttpDataResult<String>> modifySubmit(
            @RequestBody @Valid TSysDict dict, BindingResult results,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<String> result = new HttpDataResult<>(request.getRequestURI());

        if (results.hasErrors()){
            throw new CheckException(Objects.requireNonNull(results.getFieldError()).getDefaultMessage());
        }
        //初始化数据字典层级信息
        initDictLevel(dict);

        if (dict.getDictId().equals(dict.getParentId())) {
            dict.setDataLevel(1);
            dict.setParentId(null);
        }
        dictService.updateByPrimaryKeySelective(dict);

        //修改子集层级
        dictService.updateSubDictLevel(dict.getDictId());

        result.setData(dict.getDictId());

        result.setMessage("修改数据字典成功。");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }


    /**
     * 通过数据字典类型ID及上级数据字典ID获取级联数据字典数据列表
     * @param parentId   上级数据字典ID
     * @param dictId  当前编辑数据字典ID
     * @param dictTypeId  数据字典类型ID
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module=MODULE,action= OperLogActionEnum.QUERY,detail="通过数据字典类型ID及上级数据字典ID获取级联数据字典数据列表")
    @ApiOperation(value = "按条件获取数据字典子集", notes = "通过数据字典类型ID及上级数据字典ID获取级联数据字典数据列表")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "dictTypeId", value = "数据字典类型ID"),
            @ApiImplicitParam(dataType = "String", name = "parentId", value = "上级数据字典ID", required = false),
            @ApiImplicitParam(dataType = "String", name = "dictId", value = "当前编辑数据字典ID", required = false)
    })
    @GetMapping(value = "/subDictData")
    public ResponseEntity<HttpDataResult<List<TSysDictVO>>> subDictData (
            @RequestParam(value = "dictTypeId") String dictTypeId,
            @RequestParam(required = false, value = "parentId") String parentId,
            @RequestParam(required = false, value = "dictId") String dictId,
            HttpServletRequest request, HttpServletResponse response) throws Exception{

        HttpDataResult<List<TSysDictVO>> result = new HttpDataResult<>(request.getRequestURI());

        Map<String, Object> map=new HashMap<>(16);

        TSysDictExample example=new TSysDictExample();
        TSysDictExample.Criteria criteria=example.createCriteria();
        criteria.andDictTypeIdEqualTo(dictTypeId);

        if(null!=parentId && !"".equals(parentId)){
            criteria.andParentIdEqualTo(parentId);
        }else{
            criteria.andDataLevelEqualTo(1).andParentIdIsNull();
        }

        if(null!=dictId && !"".equals(dictId.trim())){
            criteria.andDictIdNotEqualTo(dictId.trim());
        }

        List<TSysDict> dictList=dictService.selectByExample(example);

        List<TSysDictVO> dictVOList=new ArrayList<>();

        TSysDictExample subExample;

        for (TSysDict dict:dictList){
            TSysDictVO dictVO=new TSysDictVO();
            BeanUtils.copyProperties(dict,dictVO);

            subExample = new TSysDictExample();
            subExample.createCriteria().andParentIdEqualTo(dict.getDictId());
            if (dictService.countByExample(subExample)>0){
                dictVO.setChildren(new ArrayList<>());
            }

            dictVOList.add(dictVO);
        }

        result.setData(dictVOList);

        result.setMessage("获取级联数据字典数据子集成功.");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);

    }



    /***
     * 数据字典启动停用变更
     * @param dictId
     * @param isEnable
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module=MODULE,action= OperLogActionEnum.UPDATE,detail="数据字典启动停用变更",isSaveRequestData=true)
    @ApiOperation(value = "数据字典启动停用变更", notes = "数据字典启动停用变更")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "dictId", value = "字典ID", required = true),
            @ApiImplicitParam(dataType = "Boolean", name = "isEnable", value = "是否启用", required = true)
    })
    @PutMapping(value = "/statusChange")
    @RequiresPermissions("data:dict:modify")
    public ResponseEntity<HttpDataResult<TSysDict>> statusChange(
            @RequestParam(value = "dictId") String dictId,
            @RequestParam( value = "isEnable") Boolean isEnable,
            HttpServletRequest request, HttpServletResponse response) throws Exception{
        HttpDataResult<TSysDict> result = new HttpDataResult<>(request.getRequestURI());
        TSysDict dict= new TSysDict();

        dict.setDictId(dictId);
        dict.setIsEnable(isEnable);

        dictService.updateByPrimaryKeySelective(dict);
        result.setData(dict);

        result.setMessage("Ok.");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);

    }

}
